	#pragma once
#include <iostream>
#include <memory>
#include <functional>
using namespace std;


class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{}

	~Date()
	{
		cout << "~Date()" << endl;
	}

	int _year;
	int _month;
	int _day;
};


template<class T>
class Shared_ptr
{
public:
	Shared_ptr(T* ptr = nullptr)
		:_ptr(ptr)
		,_pcount(new int(1))
	{}

	template<class T , class D>
	Shared_ptr(T* ptr, D del)
		: _ptr(ptr)
		, _pcount(new int(1))
		,_del(del)
	{}

	Shared_ptr(const Shared_ptr<T>& sp)
	{
		_ptr = sp._ptr;
		_pcount = sp._pcount;
		(*_pcount)++;
		_del = sp._del;
	}

	Shared_ptr<T>& operator=(const Shared_ptr<T>& sp)
	{
		if (sp._ptr != _ptr)
		{
			// 如果赋值时不相等，就得给之前的空间走一次析构
			release();

			_ptr = sp._ptr;
			_pcount = sp._pcount;
			(*_pcount)++;
			_del = sp._del;
		}
		return *this;
	}

	void release()
	{
		if (--(*_pcount) == 0)      // 最后一次释放这个空间, 需要析构
		{
			_del(_ptr);
			delete _pcount;
			_ptr = nullptr;
			_pcount = nullptr;
		}
	}

	~Shared_ptr()
	{
		release();
	}

	T* operator->()
	{
		return _ptr;
	}

	T& operator*()
	{
		return *_ptr;
	}

	T* get() const
	{
		return _ptr;
	}
	
	int use_count() const
	{
		return *_pcount;
	}

private:
	T* _ptr;
	int* _pcount;
	function<void(T*)> _del = [](T* ptr) { delete ptr; };      // 析构一个空间
};

template<class T>
class Weak_ptr
{
public:

	Weak_ptr()
		:_ptr(nullptr)
	{}

	template <class U> 
	Weak_ptr(const Shared_ptr<U>& x)
	{
		_ptr = x.get();
	}

	template <class U>
	Weak_ptr<T>& operator=(const Shared_ptr<U>& x)
	{
		_ptr = x.get();
		return *this;
	}

private:
	T* _ptr = nullptr;

};
